﻿using Newtonsoft.Json;
using Senparc.Weixin;
using Senparc.Weixin.Entities;
using Senparc.Weixin.HttpUtility;
using Senparc.Weixin.MP;
using Senparc.Weixin.MP.AdvancedAPIs;
using Senparc.Weixin.MP.AdvancedAPIs.Media;
using Senparc.Weixin.MP.AdvancedAPIs.OAuth;
using Senparc.Weixin.MP.AdvancedAPIs.User;
using Senparc.Weixin.MP.Containers;
using Senparc.Weixin.MP.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ZBJF.Warranty.BLL.Cached;
using ZBJF.Warranty.Common.Common;
using ZBJF.Warranty.Common.Enums.SocketEnum;
using ZBJF.Warranty.Model.ViewModel.SocketModel;

namespace ZBJF.Warranty.WeiXin
{
    public class WeiXinHelper
    {

        #region 检查签名是否正确 + static bool Check(string signature, string timestamp, string nonce)
        /// <summary>
        /// 检查签名是否正确
        /// </summary>
        /// <param name="signature">微信加密签名，signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数</param>
        /// <param name="timestamp">时间戳</param>
        /// <param name="nonce">随机数</param>
        /// <returns>正确：true； 错误：false</returns>
        public static bool CheckToken(string signature, string timestamp, string nonce)
        {
            bool result = CheckSignature.Check(signature, timestamp, nonce, WeiXinConfig.Token);
            if (!result)
                LogHelper.WriteLog("Token验证失败:" + WeiXinConfig.Token, LogType.tag);
            return result;
        }
        #endregion

        #region 获取AccessToken +  string GetAccessToken()
        /// <summary>
        /// 获取AccessToken
        /// </summary>
        /// <returns></returns>
        public static string GetAccessToken()
        {
            return AccessTokenContainer.TryGetAccessToken(WeiXinConfig.APPID, WeiXinConfig.APPSECRET);
        }
        #endregion

        #region 获取OAuth验证跳转Url + string GetAuthorizeUrl(string state,string redirectUrl, OAuthScope scope, bool addConnectRedirect = true)
        /// <summary>
        /// 获取OAuth验证跳转Url
        /// </summary>
        /// <param name="state">重定向后会带上state参数，开发者可以填写a-zA-Z0-9的参数值，最多128字节</param>
        /// <param name="scope">应用授权作用域，snsapi_base （不弹出授权页面，直接跳转，只能获取用户openid），snsapi_userinfo （弹出授权页面，可通过openid拿到昵称、性别、所在地。并且，即使在未关注的情况下，只要用户授权，也能获取其信息）</param>
        /// <param name="addConnectRedirect"></param>
        /// <returns></returns>
        public static string GetAuthorizeUrl(string state, string redirectUrl, OAuthScope scope, bool addConnectRedirect = true)
        {
            /* 这一步发送之后，客户会得到授权页面，无论同意或拒绝，都会返回redirectUrl页面。
             * 如果用户同意授权，页面将跳转至 redirect_uri/?code=CODE&state=STATE。这里的code用于换取access_token（和通用接口的access_token不通用）
             * 若用户禁止授权，则重定向后不会带上code参数，仅会带上state参数redirect_uri?state=STATE
             */
            var url =
                string.Format("https://open.weixin.qq.com/connect/oauth2/authorize?appid={0}&redirect_uri={1}&response_type={2}&scope={3}&state={4}{5}#wechat_redirect",
                                WeiXinConfig.APPID.AsUrlData(), redirectUrl.AsUrlData(), "code".AsUrlData(), scope.ToString("g").AsUrlData(), state.AsUrlData(),
                                addConnectRedirect ? "&connect_redirect=1" : "");

            return url;
        }
        #endregion

        #region 获取用户OpenId + string GetOpenId(string code)
        /// <summary>
        /// 获取用户OpenId
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        public static OAuthAccessTokenResult GetWeiXinUserInfo(string code)
        {
            OAuthAccessTokenResult result = null;
            try
            {
                result = OAuthApi.GetAccessToken(WeiXinConfig.APPID, WeiXinConfig.APPSECRET, code);
                if (result == null || result.errcode != ReturnCode.请求成功)
                {
                    LogHelper.WriteLog(string.Format("获取用户信息失败;Appid:{0};AppSecret:{1};code:{2};\r\n 请求结果：{3}", WeiXinConfig.APPID, WeiXinConfig.APPSECRET, code, JsonConvert.SerializeObject(result)), LogType.remark);
                }
                return result;
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(string.Format("获取用户信息失败;Appid:{0};AppSecret:{1};code:{2};\r\n 请求结果：{3};\r\n异常信息：{4}", WeiXinConfig.APPID, WeiXinConfig.APPSECRET, code, JsonConvert.SerializeObject(result), ex.ToString()), LogType.remark);
                return result;
            }
        }
        #endregion

        #region 获取授权用户信息 +  static OAuthUserInfo GetUserInfo(string openId)
        /// <summary>
        /// 获取授权用户信息
        /// </summary>
        /// <param name="accessToken">调用接口凭证</param>
        /// <param name="openId">普通用户的标识，对当前公众号唯一</param>
        /// <param name="lang">返回国家地区语言版本，zh_CN 简体，zh_TW 繁体，en 英语</param>
        /// <returns></returns>
        public static OAuthUserInfo GetUserInfo(string openId)
        {
            try
            {
                string accesstoken = AccessTokenContainer.TryGetAccessToken(WeiXinConfig.APPID, WeiXinConfig.APPSECRET);
                return OAuthApi.GetUserInfo(accesstoken, openId, Language.zh_CN);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog("获取微信授权用户基本信息异常：" + ex.ToString(), LogType.error);
            }
            return null;
        }
        #endregion

        #region 获取用户基本信息 + UserInfoJson GetUserInfoBase(string openId)
        /// <summary>
        /// 获取用户基本信息
        /// </summary>
        /// <param name="openId"></param>
        /// <returns></returns>
        public static UserInfoJson GetUserInfoBase(string openId)
        {
            try
            {
                string accesstoken = AccessTokenContainer.TryGetAccessToken(WeiXinConfig.APPID, WeiXinConfig.APPSECRET);
                return UserApi.Info(accesstoken, openId, Language.zh_CN);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog("获取微信用户基本信息异常：" + ex.ToString(), LogType.error);
            }
            return null;
        }
        #endregion

        #region 发送客服文本消息 + static bool SendCustomerServiceMessage(string openId, string message)
        /// <summary>
        /// 发送客服文本消息
        /// </summary>
        /// <param name="openId">用户OpenId</param>
        /// <param name="message">消息内容</param>
        /// <returns></returns>
        public static bool SendCustomerServiceMessage_Text(string openId, string message)
        {
            try
            {
                string accesstoken = AccessTokenContainer.TryGetAccessToken(WeiXinConfig.APPID, WeiXinConfig.APPSECRET);
                WxJsonResult result = CustomApi.SendText(accesstoken, openId, message);
                if (result.errcode == ReturnCode.请求成功)
                {
                    return true;
                }
                else
                {
                    LogHelper.WriteLog("发送客服文本消息失败：" + JsonConvert.SerializeObject(result), LogType.remark);
                    return false;
                }
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog("发送客服文本消息异常：" + ex.ToString(), LogType.error);
            }
            return false;
        }
        #endregion

        #region 发送客服图文消息 + static bool SendCustomerServiceMessage_ImageText(string openId, string picUrl, string message = "", string title = "", string url = "")
        /// <summary>
        /// 发送客服图文消息
        /// </summary>
        /// <param name="openId">用户OpenId</param>
        /// <param name="picUrl">图片地址</param>
        /// <param name="message">消息内容</param>
        /// <param name="title">标题</param>
        /// <param name="url">跳转到</param>
        /// <returns></returns>
        public static bool SendCustomerServiceMessage_ImageText(string openId, string picUrl)
        {
            try
            {
                string accesstoken = AccessTokenContainer.TryGetAccessToken(WeiXinConfig.APPID, WeiXinConfig.APPSECRET);
                List<Article> ar = new List<Article>() {
                     new Article { PicUrl= picUrl}
                };
                WxJsonResult result = CustomApi.SendNews(accesstoken, openId, ar);
                if (result.errcode == ReturnCode.请求成功)
                {
                    return true;
                }
                else
                {
                    LogHelper.WriteLog("发送客服图文消息失败：" + JsonConvert.SerializeObject(result), LogType.remark);
                    return false;
                }
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog("发送客服图文消息异常：" + ex.ToString(), LogType.error);
            }
            return false;
        }
        #endregion

        #region 保存微信声音素材
        /// <summary>
        /// 保存微信声音素材
        /// </summary>
        /// <param name="accesstoken"></param>
        /// <param name="mediaId"></param>
        /// <param name="path">保存路径(c:sss)</param>
        /// <param name="fileType">文件后缀名(mp4)</param>
        /// <returns></returns>
        public static bool LoadVoiceFile(string accesstoken, string mediaId, string path, string fileName)
        {
            try
            {
                string reault = MediaApi.Get(accesstoken, mediaId, path + fileName);
                if (string.IsNullOrEmpty(reault))
                {
                    return false;
                }
                else
                    return true;
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog("保存微信声音素材异常：" + ex.ToString(), LogType.error);
            }
            return false;
        }


        #endregion


        #region 获取H5站点的AccessToken +  string GetH5AccessToken()
        /// <summary>
        /// 获取H5站点的AccessToken
        /// </summary>
        /// <returns></returns>
        public static string GetH5AccessToken()
        {
            WebUtils web = new WebUtils();
            try
            {
                string result = web.DoGet(WeiXinConfig.H5SiteUrl + "/api/WeiXinApi/GetAccessToken", null);
                if (string.IsNullOrEmpty(result))
                {
                    LogHelper.WriteLog("获取H5站点的AccessToken失败", LogType.remark);
                    return null;
                }
                ResultModel model = JsonConvert.DeserializeObject<ResultModel>(result);
                if (model == null || !model.Result || model.CodeState != CodeStateEnum.Success || model.Data == null)
                {
                    LogHelper.WriteLog("获取H5站点的AccessToken失败:" + result, LogType.remark);
                    return null;
                }

                return NetCryptoHelper.AesDecrypt(model.Data.ToString(), "zbjf_accessToken_20180109_~!@#$%");
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog("获取H5站点的AccessToken异常：" + ex.ToString(), LogType.error);
            }
            return null;
        }
        #endregion

        #region 获取用户基本信息 + UserInfoJson GetUserInfoBase(string openId, string accesstoken)
        /// <summary>
        /// 获取用户基本信息
        /// </summary>
        /// <param name="openId"></param>
        /// <returns></returns>
        public static UserInfoJson GetUserInfoBase(string openId, string accesstoken)
        {
            if (string.IsNullOrEmpty(accesstoken))
                return null;
            try
            {
                return UserApi.Info(accesstoken, openId, Language.zh_CN);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog("获取微信用户基本信息异常：" + ex.ToString(), LogType.error);
            }
            return null;
        }
        #endregion

        #region 发送客服文本消息 + static bool SendCustomerServiceMessage(string openId, string message, string accesstoken)
        /// <summary>
        /// 发送客服文本消息
        /// </summary>
        /// <param name="openId">用户OpenId</param>
        /// <param name="message">消息内容</param>
        /// <returns></returns>
        public static bool SendCustomerServiceMessage_Text(string openId, string message, string accesstoken)
        {
            if (string.IsNullOrEmpty(accesstoken))
                return false;
            try
            {
                WxJsonResult result = CustomApi.SendText(accesstoken, openId, message);
                if (result.errcode == ReturnCode.请求成功)
                {
                    return true;
                }
                else
                {
                    LogHelper.WriteLog("发送客服文本消息失败：" + JsonConvert.SerializeObject(result), LogType.remark);
                    return false;
                }
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog("发送客服文本消息异常：" + ex.ToString(), LogType.error);
            }
            return false;
        }
        #endregion

        #region 发送客服图片消息 + static bool SendCustomerServiceMessage_Image(string openId, string medieId, string accesstoken)
        /// <summary>
        /// 发送客服图片消息
        /// </summary>
        /// <param name="openId"></param>
        /// <param name="mediaId">微信的文件Media_id</param>
        /// <param name="accesstoken"></param>
        /// <returns></returns>
        public static bool SendCustomerServiceMessage_Image(string openId, string mediaId, string accesstoken)
        {
            if (string.IsNullOrEmpty(accesstoken))
                return false;
            try
            {
                WxJsonResult result = CustomApi.SendImage(accesstoken, openId, mediaId);
                if (result.errcode == ReturnCode.请求成功)
                {
                    return true;
                }
                else
                {
                    LogHelper.WriteLog("发送客服图片消息失败：" + JsonConvert.SerializeObject(result), LogType.remark);
                    return false;
                }
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog("发送客服图片消息异常：" + ex.ToString(), LogType.error);
            }
            return false;
        }
        #endregion

        #region 发送客服图文消息 + static  bool SendCustomerServiceMessage_ImageText(string openId, string picUrl, string accesstoken, string message = "", string title = "", string url = "")
        /// <summary>
        /// 发送客服图文消息
        /// </summary>
        /// <param name="openId">用户OpenId</param>
        /// <param name="picUrl">图片地址</param>
        /// <param name="message">消息内容</param>
        /// <param name="title">标题</param>
        /// <param name="url">跳转到</param>
        /// <returns></returns>
        public static bool SendCustomerServiceMessage_ImageText(string openId, string picUrl, string accesstoken)
        {
            if (string.IsNullOrEmpty(accesstoken))
                return false;
            try
            {
                List<Article> ar = new List<Article>() {
                     new Article { PicUrl= picUrl}
                };
                WxJsonResult result = CustomApi.SendNews(accesstoken, openId, ar);
                if (result.errcode == ReturnCode.请求成功)
                {
                    return true;
                }
                else
                {
                    LogHelper.WriteLog("发送客服图文消息失败：" + JsonConvert.SerializeObject(result), LogType.remark);
                    return false;
                }
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog("发送客服图文消息异常：" + ex.ToString(), LogType.error);
            }
            return false;
        }
        #endregion

        #region 上传图片临时素材 + string UploadTemporaryMedia(string accessToken, Senparc.Weixin.MP.UploadMediaFileType fileType, string fileFullName)
        /// <summary>
        /// 上传图片临时素材
        /// </summary>
        /// <param name="accessToken"></param>
        /// <param name="fileType">文件类型</param>
        /// <param name="fileFullName">文件当前绝对路径</param>
        /// <returns>微信media_id</returns>
        public static string UploadTemporaryMedia(string accessToken, Senparc.Weixin.MP.UploadMediaFileType fileType, string fileFullName)
        {
             UploadTemporaryMediaResult resultUpload = MediaApi.UploadTemporaryMedia(accessToken, fileType, fileFullName);
            if (resultUpload == null || string.IsNullOrEmpty(resultUpload.media_id)) {
                return null;
            }
            return resultUpload.media_id;
        }
        #endregion
    }
}
